package com.example.dayu521.sg_oss.service.impl;

import com.example.dayu521.sg_oss.conf.AmqpCnf;
import com.example.dayu521.sg_oss.domain.NumSplit;
import com.example.dayu521.sg_oss.service.OrderNumService;
import com.example.dayu521.sg_oss.service.OrderNumSource;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Component
public class OrderNumServiceImpl implements OrderNumService {

    @Autowired
    private OrderNumSource orderNumSource;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    private final static class DefaultNumState implements NumState{
        public long base;
        public long bound;
        public String num_key;

        public long node_id;
        public boolean is_expire;
        public long res;

        public OrderNumServiceImpl orderNumService;

        @Override
        public boolean is_expire() {
            return is_expire;
        }

        @Override
        public long getRes() {
            return res;
        }

        @Override
        public long get_next_num() {
            return orderNumService.get_next_num(this);
        }

        @Override
        public boolean valid(long res) {
            return orderNumService.valid(this,res);
        }
    }

    @Override
    public NumState get_num_state() {
        DefaultNumState numState = new DefaultNumState();
        numState.orderNumService=this;

        Long random_node = orderNumSource.get_random_node();
        Object o = orderNumSource.pull_from(random_node,"sg_oss.incrby");

        if(o!=null){
            NumSplit res = new NumSplit();
            BeanUtils.copyProperties(o,res);

            numState.is_expire=false;
            numState.node_id=random_node;
            numState.num_key=res.getIncr_key();
            numState.base=res.getBase();
            numState.bound=res.getUp_bound();

        }else{
            numState.is_expire=true;
            numState.num_key="";
            rabbitTemplate.convertAndSend(AmqpCnf.order_exehange,AmqpCnf.order_incrby_null_bind_key,random_node);
        }
        return numState;
    }

//    private final static Pattern compile = Pattern.compile("""
//            ^\\{(\\d+)}\\.(.+)""");

    public long get_next_num(DefaultNumState state) {
        return orderNumSource.get_next_long(state.node_id,state.num_key);
    }

    public boolean valid(DefaultNumState state, long res) {
        //校验结果.需要numstate和返回的res作为校验参数  => 如果为0,校验结果是true,但也提前初始化下个阶段,如果小于0,则直接初始化
        // 初始化返回值v为false.1 如果大于0,v=true 2 如果v小于0,恢复 3如果v=0
        if(state.is_expire()){
            return false;
        }
        boolean ok = false;
        if (res>0){
            ok=true;
        }else{
            NumSplit o = new NumSplit();
            o.setBase(state.base);
            o.setNode_id(Long.toString(state.node_id));
            rabbitTemplate.convertAndSend("sg.order.exchange","sg.order.key",o);
            if(res==0){
                ok=true;
            }
        }
        state.res=state.base+state.bound-res;

        return ok;
    }
}
